//Custome the Data Structure

use serde::{Serialize, Serializer};
use serde::ser::SerializeStruct;


// 1. primitive type    12 
// bool, i(8,16,32,64),  u(8,16,32,64), f(32,64), char
//
// 2. Option(none, some) , Unit   3
//
// 2. str, string, bytes   3
//
// 3. seq & map         2
//    seq - Vec<u8> 
//    map - Map<u8>
//
// 4. tuple,  distinction with seq  1
//  ===> tuple && array 
//      tuple => statically sized sequence, 
//           the length does not need to be serialized, 
//           the length will be known at deserialization time.
//           e.g. [T; 16], (i8, &str, char)
//
//      seq  =>  a variably sized sequence,
//           the length have to be serialized
//           the length will be not known at deserialization time.
//           e.g. Vec<T>
//
// 5. struct    4
//  5.1 struct 
//  5.2 tuple_struct,   struct x(f64, f64)
//  5.3 newtype_struct, struct x(u64)
//  5.4 unit_struct     struct x;
//
// 6. enum variants   4
//  enum E {
//      6.1 struct_variant  Color {r:u8, g:u8, b:u8}
//      6.2 tuple_variant   X(f64, f64)
//      6.3 newtype_variant X(u64)
//      6.4 unit_variant    X
//  }//end of enum E 


// Struct  ***********************************
struct Order {
    id: i32,
    name: String,
}

impl Serialize for Order {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 
    where 
        S: Serializer
    {
        let mut field = serializer.serialize_struct("Order", 2)?;
        field.serialize_field("id", &self.id)?;
        field.serialize_field("name", &self.name)?;
        field.end()
    }
}

// A tuple struct. Use three-step process:
//   1. serialize_tuple_struct
//   2. serialize_field
//   3. end
// struct Point2D(f64, f64);

// A newtype struct. Use serialize_newtype_struct.
// struct Inches(u64);

// A unit struct. Use serialize_unit_struct.
// struct Instance;


#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn ser_order(){
        let order = Order{ id: 1, name: "Hello".to_string()};
        let expect = r#"{"id":1,"name":"Hello"}"#;
        let order_json = serde_json::to_string(&order).unwrap();
        assert_eq!(expect, order_json);
    }
}

